ModelForm
1.ModeForm简单验证
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from django.db import models# Create your models here.class UserInfo(models.Model): # verbose_name 等同于Form类里面的label username = models.CharField(verbose_name='用户',max_length=32) email = models.EmailField(verbose_name='邮件') user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id')class UserType(models.Model): caption = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象 return self.captionmodels.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
index.htmlTitle
views.py
from django.shortcuts import render,redirectfrom app01 import modelsfrom django import formsfrom django.forms import fieldsclass UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo # 去UserInfo类中获取数据 fields = '__all__' # __all__ 代指所有字段 # fields = ['username','email'] #指定显示的字段 # exclude = ['username'] #不显示的字段def index(request): if request.method == 'GET': obj = UserInfoModelForm() return render(request,'index.html',{ 'obj':obj}) elif request.method == 'POST': obj = UserInfoModelForm(request.POST) result = obj.is_valid() if result: print(obj.cleaned_data) #如果models里没有__str__方法,则user_type获取 #到的是一个对象,可直接根据对象进行操作 print(obj.cleaned_data['user_type']) # {'username': 'James', 'user_type': < UserType: 超级用户 >, 'email': 'ffd@fdsf.com'} # 超级用户 else: print(obj.errors) return render(request,'index.html',{ 'obj':obj})
注:ModelForm最终继承了BaseForm,BaseForm里面具有is_valid方法,所以ModelForm也可以用is_valid进行验证
2.ModelForm组件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信息 labels ={'username':'用户名'}可写多个 help_texts=None, # 帮助提示信息 help_texts = {'username':'help info'} widgets=None, # 自定义插件 error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS) field_classes=None # 自定义字段类 (也可以自定义字段) localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据 如: 数据库中 2016-12-27 04:10:57 setting中的配置 TIME_ZONE = 'Asia/Shanghai' USE_TZ = True 则显示: 2016-12-27 12:10:57 b. 验证执行过程 is_valid -> full_clean -> 钩子 -> 整体错误 c. 字典字段验证 def clean_字段名(self): # 可以抛出异常 # from django.core.exceptions import ValidationError return "新值" d. 用于验证 model_form_obj = XXOOModelForm() model_form_obj.is_valid() model_form_obj.errors.as_json() model_form_obj.clean() model_form_obj.cleaned_data e. 用于创建 model_form_obj = XXOOModelForm(request.POST) #### 页面显示,并提交 ##### # 默认保存多对多 obj = form.save(commit=True) # 不做任何操作,内部定义 save_m2m(用于保存多对多) obj = form.save(commit=False) obj.save() # 保存单表信息 obj.save_m2m() # 保存关联多对多信息 f. 用于更新和初始化 obj = model.tb.objects.get(id=1) model_form_obj = XXOOModelForm(request.POST,instance=obj) ... PS: 单纯初始化 model_form_obj = XXOOModelForm(initial={...})ModelForm所有组件
(1)自定义插件widgets
from django.forms import widgets as Fwidgets #避免跟widgets重名class UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo #去UserInfo类中获取数据 fields = '__all__' #__all__ 代指所有字段 labels ={ 'username':'用户名'} help_texts = { 'username':'...'} widgets = { 'username':Fwidgets.Textarea(attrs={ 'class':'c1'}) }
(2)错误信息error_message
from django.forms import widgets as Fwidgets #避免跟widgets重名class UserInfoModelForm(forms.ModelForm): class Meta: ---snip--- error_messages = { '__all__':{}, #整体的错误信息 'email':{ 'required':'邮箱不能为空'} }
(3)自定义更改字段验证规则field_classses
from django.forms import fields as Ffields #避免跟fields重名class UserInfoModelForm(forms.ModelForm): class Meta: ---snip--- field_classes ={ 'email':Ffields.URLField #把邮件格式改为url格式验证 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from django.shortcuts import render,redirectfrom app01 import modelsfrom django import formsfrom django.forms import fieldsfrom django.forms import widgets as Fwidgetsfrom django.forms import fields as Ffields class UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo # 去UserInfo类中获取数据 fields = '__all__' # __all__ 代指所有字段 labels = { 'username': '用户名'} help_texts = { 'username': '...'} widgets = { 'username': Fwidgets.Textarea(attrs={ 'class': 'c1'}) } error_messages = { '__all__': {}, # 整体的错误信息 'email': { 'required': '邮箱不能为空'} } field_classes = { 'email': Ffields.URLField # 把邮件格式改为url格式验证 }def index(request): if request.method == 'GET': obj = UserInfoModelForm() return render(request,'index.html',{ 'obj':obj}) elif request.method == 'POST': obj = UserInfoModelForm(request.POST) result = obj.is_valid() if result: print(obj.cleaned_data) #如果models里没有__str__方法,则user_type获取 #到的是一个对象,可直接根据对象进行操作 print(obj.cleaned_data['user_type']) # {'username': 'James', 'user_type': < UserType: 超级用户 >, 'email': 'ffd@fdsf.com'} # 超级用户 else: print(obj.errors) return render(request,'index.html',{ 'obj':obj})
3.ModelForm创建保存数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from django.db import models# Create your models here.class UserInfo(models.Model): # verbose_name 等同于Form类里面的label username = models.CharField(verbose_name='用户',max_length=32) email = models.EmailField(verbose_name='邮件') user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id') user_group = models.ManyToManyField('UserGroup')class UserType(models.Model): caption = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象 return self.captionclass UserGroup(models.Model): groupname = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象 return self.groupname
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
Title
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from django import formsfrom app import modelsfrom django.forms import widgets as Fwidgets #避免跟widgets重名from django.forms import fields as Ffields #避免跟fields重名class UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo #去UserInfo类中获取数据 fields = '__all__' #__all__ 代指所有字段 labels ={ 'username':'用户名'} help_texts = { 'username':'...'} widgets = { 'username':Fwidgets.Textarea(attrs={ 'class':'c1'}) } error_messages = { '__all__':{}, #整体的错误信息 'email':{ 'required':'邮箱不能为空'} }ModelForm验证
处理文件
from django.shortcuts import renderdef index(request): if request.method == 'GET': obj = UserInfoModelForm() return render(request,'index.html',{ 'obj':obj}) elif request.method == 'POST': obj = UserInfoModelForm(request.POST) if obj.is_valid(): # 验证成功直接保存 obj.save() #默认commit=True,会保存多对多 # 保存一对多表单 # instance = obj.save(commit=False) # instance.save() # 保存多对多数据 # obj.save_m2m() return render(request,'index.html',{ 'obj':obj})
4.ModelForm更新和初始化
描述:打开用户列表,显示用户信息,点击编辑跳转到编辑页面,Input显示选择用户的当前值;提交后,对数据进行更新
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/$', views.index), url(r'^list/$', views.user_list), url(r'^edit-(\d+)', views.user_edit),]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
from django.db import modelsclass UserInfo(models.Model): # verbose_name 等同于Form类里面的label username = models.CharField(verbose_name='用户',max_length=32) email = models.EmailField(verbose_name='邮件') user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id') user_group = models.ManyToManyField('UserGroup')class UserType(models.Model): caption = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象 return self.captionclass UserGroup(models.Model): groupname = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象 return self.groupname
user_list.html
Title
- {% for row in list %}
{
{ row.username }}--{ { row.user_type.caption }}--编辑 {% endfor %}user_edit.html
Title
views.py
from django.shortcuts import render,redirectfrom app01 import modelsfrom django import formsfrom django.forms import fieldsfrom django.forms import widgets as Fwidgetsfrom django.forms import fields as Ffieldsclass UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo # 去UserInfo类中获取数据 fields = '__all__' # __all__ 代指所有字段 labels = { 'username': '用户名'} help_texts = { 'username': '...'} widgets = { 'username': Fwidgets.Textarea(attrs={ 'class': 'c1'}) } error_messages = { '__all__': {}, # 整体的错误信息 'email': { 'required': '邮箱不能为空'} }def index(request): if request.method == 'GET': obj = UserInfoModelForm() return render(request,'index.html',{ 'obj':obj}) elif request.method == 'POST': obj = UserInfoModelForm(request.POST) if obj.is_valid(): # 验证成功直接保存 obj.save() #默认commit=True,会保存多对多 # 保存一对多表单 # instance = obj.save(commit=False) # instance.save() # 保存多对多数据 # obj.save_m2m() return render(request,'index.html',{ 'obj':obj})def user_list(request): if request.method == 'GET': list = models.UserInfo.objects.all().select_related('user_type') return render(request, 'user_list.html', { 'list': list})def user_edit(request, nid): if request.method == 'GET': user_obj = models.UserInfo.objects.filter(id=nid).first() obj = UserInfoModelForm(instance=user_obj) # instance显示user_obj的对应值 return render(request, 'user_edit.html', { 'obj': obj, 'nid': nid}) elif request.method == 'POST': user_obj = models.UserInfo.objects.filter(id=nid).first() obj = UserInfoModelForm(request.POST, instance=user_obj) # instance更新user_obj而不是添加 if obj.is_valid(): # 验证成功直接更新 obj.save() else: print(obj.errors.as_json()) return render(request, 'user_edit.html', { 'obj': obj, 'nid': nid})